module aru_reduce_sum_4_to_1 (
    input  logic  clk,
    input  logic  rst_n,
    input  logic  en,
    input  logic  psum_en,           // 累加使能信号
    input  logic  end_reduce,        // 结束累加信号
    input  logic  dat_in_vld [3:0],
    input  fp32_t dat_in     [3:0],
    output fp32_t dat_out,
    output logic  dat_out_vld
);

    // IEEE 754 单精度浮点数固定参数
    localparam int INPUTS = 4;
    localparam int DWIDTH = 32;
    localparam int EWIDTH = 8;
    localparam int MWIDTH = 23;
    localparam int BIAS = 127;
    localparam int RWIDTH = 26;

    // 计算衍生参数
    localparam int SIGNIFICAND_WIDTH = MWIDTH + 1;
    localparam int ALIGNED_WIDTH = SIGNIFICAND_WIDTH + RWIDTH;
    localparam int GUARD_BITS = 11;
    localparam int CSA_WIDTH = ALIGNED_WIDTH + GUARD_BITS + 1;
    localparam int LOD_WIDTH = $clog2(CSA_WIDTH);

    localparam int MAX_EXP = (1 << EWIDTH) - 1;
    localparam logic [EWIDTH-1:0] EXP_ZEROS = '0;
    localparam logic [EWIDTH-1:0] EXP_ONES = '1;
    localparam logic [MWIDTH-1:0] MANT_ZEROS = '0;
    localparam fp32_t NAN = {1'b0, 8'hff, 23'h400000};


    typedef struct packed {
        logic              sign;
        logic [EWIDTH-1:0] exponent;
        logic [MWIDTH-1:0] mantissa;
    } ieee754_t;

    // 特殊值检测结构
    typedef struct packed {
        logic is_inf;
        logic is_nan;
        logic is_zero;
        logic is_subnormal;
    } special_flags_t;

    //==========================================================================
    // Stage 1: 输入解析 + 特殊值检测 + 最大指数查找
    //==========================================================================

    // Stage 1 组合逻辑信号
    ieee754_t                               operand_array[INPUTS];
    logic           [           EWIDTH-1:0] exponents    [INPUTS];
    logic           [SIGNIFICAND_WIDTH-1:0] significands [INPUTS];
    logic                                   signs        [INPUTS];
    special_flags_t                         special_flags[INPUTS];
    logic           [           EWIDTH-1:0] max_exponent;
    logic any_inf_s0, any_nan_s0;
    logic [INPUTS-1:0] is_inf, is_nan, is_zero;

    // Stage 1 寄存器
    logic [           EWIDTH-1:0] exponents_s1    [INPUTS];
    logic [SIGNIFICAND_WIDTH-1:0] significands_s1 [INPUTS];
    logic                         signs_s1        [INPUTS];
    logic [           EWIDTH-1:0] max_exponent_s1;
    logic any_inf_s1, any_nan_s1;
    logic              psum_en_s1;
    logic              end_reduce_s1;

    // 最大指数查找的中间信号
    logic [EWIDTH-1:0] max_exp_stage1[INPUTS/2];

    // Stage 1 组合逻辑 - 添加 dat_in_vld 检查
    always_comb begin
        for (int i = 0; i < INPUTS; i++) begin
            if (dat_in_vld[i] && en) begin
                operand_array[i] = dat_in[i];

                // 提取IEEE 754字段
                signs[i] = operand_array[i].sign;
                exponents[i] = operand_array[i].exponent;

                // 检查特殊值
                special_flags[i].is_inf = (&exponents[i]) & (~|operand_array[i].mantissa);
                special_flags[i].is_nan = (&exponents[i]) & (|operand_array[i].mantissa);
                special_flags[i].is_zero = (~|exponents[i]) & (~|operand_array[i].mantissa);
                special_flags[i].is_subnormal = (~|exponents[i]) & (|operand_array[i].mantissa);

                // 处理隐含位：规格化数隐含位为1，非规格化数为0
                significands[i] = (|exponents[i]) ? {1'b1, operand_array[i].mantissa} :
                                                   {1'b0, operand_array[i].mantissa};

                exponents[i] = (|exponents[i]) ? operand_array[i].exponent : 8'b1;

                // 特殊值标志
                is_inf[i] = special_flags[i].is_inf;
                is_nan[i] = special_flags[i].is_nan;
                is_zero[i] = special_flags[i].is_zero;
            end else begin
                // dat_in_vld[i]=0，按照0处理
                operand_array[i]              = '0;
                signs[i]                      = '0;
                exponents[i]                  = '0;
                significands[i]               = '0;
                special_flags[i].is_inf       = '0;
                special_flags[i].is_nan       = '0;
                special_flags[i].is_zero      = 1'b1;  // 标记为零
                special_flags[i].is_subnormal = '0;
                is_inf[i]                     = '0;
                is_nan[i]                     = '0;
                is_zero[i]                    = 1'b1;
            end
        end

        any_inf_s0 = |is_inf;
        any_nan_s0 = |is_nan;
    end

    // 找到最大指数 - 4输入树形结构
    always_comb begin
        for (int i = 0; i < INPUTS / 2; i++) begin
            max_exp_stage1[i] = (exponents[i*2] > exponents[i*2+1]) ? exponents[i*2] : exponents[i*2+1];
        end
        max_exponent = (max_exp_stage1[0] > max_exp_stage1[1]) ? max_exp_stage1[0] : max_exp_stage1[1];
    end

    // Stage 1 寄存器
    always_ff @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            for (int i = 0; i < INPUTS; i++) begin
                exponents_s1[i]    <= '0;
                significands_s1[i] <= '0;
                signs_s1[i]        <= '0;
            end
            max_exponent_s1 <= '0;
            any_inf_s1      <= '0;
            any_nan_s1      <= '0;
            psum_en_s1      <= '0;
            end_reduce_s1   <= '0;
        end else if (en) begin
            for (int i = 0; i < INPUTS; i++) begin
                exponents_s1[i]    <= exponents[i];
                significands_s1[i] <= significands[i];
                signs_s1[i]        <= signs[i];
            end
            max_exponent_s1 <= max_exponent;
            any_inf_s1      <= any_inf_s0;
            any_nan_s1      <= any_nan_s0;
            psum_en_s1      <= psum_en;
            end_reduce_s1   <= end_reduce;
        end
    end

    //==========================================================================
    // Stage 2: 对阶移位
    //==========================================================================

    // Stage 2 组合逻辑信号
    logic [       EWIDTH-1:0] exp_diffs              [INPUTS];
    logic [ALIGNED_WIDTH-1:0] aligned_significands   [INPUTS];

    // Stage 2 寄存器
    logic [ALIGNED_WIDTH-1:0] aligned_significands_s2[INPUTS];
    logic                     signs_s2               [INPUTS];
    logic [       EWIDTH-1:0] max_exponent_s2;
    logic any_inf_s2, any_nan_s2;
    logic psum_en_s2;
    logic end_reduce_s2;

    // Stage 2 组合逻辑：对阶移位
    always_comb begin
        for (int i = 0; i < INPUTS; i++) begin
            exp_diffs[i] = max_exponent_s1 - exponents_s1[i];

            if (exp_diffs[i] > ALIGNED_WIDTH - 1) begin
                aligned_significands[i] = '0;
            end else begin
                aligned_significands[i] = ({significands_s1[i], {RWIDTH{1'b0}}} >> exp_diffs[i]);
            end
        end
    end

    // Stage 2 寄存器
    always_ff @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            for (int i = 0; i < INPUTS; i++) begin
                aligned_significands_s2[i] <= '0;
                signs_s2[i]                <= '0;
            end
            max_exponent_s2 <= '0;
            any_inf_s2      <= '0;
            any_nan_s2      <= '0;
            psum_en_s2      <= '0;
            end_reduce_s2   <= '0;
        end else if (en) begin
            for (int i = 0; i < INPUTS; i++) begin
                aligned_significands_s2[i] <= aligned_significands[i];
                signs_s2[i]                <= signs_s1[i];
            end
            max_exponent_s2 <= max_exponent_s1;
            any_inf_s2      <= any_inf_s1;
            any_nan_s2      <= any_nan_s1;
            psum_en_s2      <= psum_en_s1;
            end_reduce_s2   <= end_reduce_s1;
        end
    end

    //==========================================================================
    // Stage 3: CSA树累加
    //==========================================================================

    // Stage 3 组合逻辑信号
    logic signed [       CSA_WIDTH-1:0] signed_significands   [INPUTS];
    logic        [       CSA_WIDTH-1:0] csa_tree_in           [INPUTS];
    logic        [INPUTS*CSA_WIDTH-1:0] csa_tree_input_packed;
    logic [CSA_WIDTH-1:0] csa_sum, csa_carry;
    logic signed [CSA_WIDTH-1:0] current_accumulator;

    // Stage 3 寄存器
    logic signed [CSA_WIDTH-1:0] current_accumulator_s3;
    logic        [   EWIDTH-1:0] max_exponent_s3;
    logic any_inf_s3, any_nan_s3;
    logic psum_en_s3;
    logic end_reduce_s3;

    // Stage 3 组合逻辑：补码转换和CSA树
    always_comb begin
        for (int i = 0; i < INPUTS; i++) begin
            logic [CSA_WIDTH-1:0] extended_significand;
            extended_significand = {{GUARD_BITS + 1{1'b0}}, aligned_significands_s2[i]};

            signed_significands[i] = signs_s2[i] ? (~extended_significand + 1'b1) : extended_significand;

            csa_tree_in[i] = signed_significands[i];
            csa_tree_input_packed[i*CSA_WIDTH+:CSA_WIDTH] = csa_tree_in[i];
        end
    end

    // CSA树进行累加
    acc_csa_tree #(
        .num_inputs (INPUTS),
        .input_width(CSA_WIDTH)
    ) u_acc_csa_tree (
        .INPUT(csa_tree_input_packed),
        .OUT0 (csa_sum),
        .OUT1 (csa_carry)
    );

    assign current_accumulator = csa_sum + csa_carry;

    // Stage 3 寄存器
    always_ff @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            current_accumulator_s3 <= '0;
            max_exponent_s3        <= '0;
            any_inf_s3             <= '0;
            any_nan_s3             <= '0;
            psum_en_s3             <= '0;
            end_reduce_s3          <= '0;
        end else if (en) begin
            current_accumulator_s3 <= current_accumulator;
            max_exponent_s3        <= max_exponent_s2;
            any_inf_s3             <= any_inf_s2;
            any_nan_s3             <= any_nan_s2;
            psum_en_s3             <= psum_en_s2;
            end_reduce_s3          <= end_reduce_s2;
        end
    end

    //==========================================================================
    // Stage 4: 历史值对阶 + 最终累加
    //==========================================================================

    // 历史值寄存器
    logic signed [CSA_WIDTH-1:0] history_accumulator;
    logic        [   EWIDTH-1:0] history_max_exponent;
    logic                        history_valid;
    logic history_any_inf, history_any_nan;

    // Stage 4 组合逻辑信号
    logic [EWIDTH-1:0] global_max_exp;
    logic [EWIDTH-1:0] history_exp_diff, current_exp_diff;
    logic signed [CSA_WIDTH-1:0] aligned_history_acc;
    logic signed [CSA_WIDTH-1:0] aligned_current_acc;
    logic signed [CSA_WIDTH-1:0] final_accumulator;

    // Stage 4 寄存器
    logic signed [CSA_WIDTH-1:0] accumulator_s4;
    logic        [   EWIDTH-1:0] max_exponent_s4;
    logic any_inf_s4, any_nan_s4;
    logic end_reduce_s4;

    // 历史值与当前值对阶逻辑
    // 历史值与当前值对阶逻辑
    always_comb begin
        if (!history_valid || !psum_en_s3) begin
            // 没有历史值或未使能累加，直接使用当前累加结果
            global_max_exp      = max_exponent_s3;
            aligned_history_acc = '0;
            aligned_current_acc = current_accumulator_s3;
            final_accumulator   = current_accumulator_s3;
        end else begin
            // 比较历史最大指数和当前最大指数
            global_max_exp   = (history_max_exponent > max_exponent_s3) ? history_max_exponent : max_exponent_s3;

            // 计算指数差
            history_exp_diff = global_max_exp - history_max_exponent;
            current_exp_diff = global_max_exp - max_exponent_s3;

            // 对较小指数的累加器进行右移
            // 关键：对补码进行右移时，需要保持符号位不变，相当于带符号的缩小
            if (history_exp_diff > CSA_WIDTH - 1) begin
                // 指数差太大，值趋近于0，但需要保留符号趋势
                aligned_history_acc = '0;
            end else begin
                // 方法：将补码视为unsigned进行逻辑右移，保持数值关系
                aligned_history_acc = $signed($unsigned(history_accumulator) >> history_exp_diff);
            end

            if (current_exp_diff > CSA_WIDTH - 1) begin
                aligned_current_acc = '0;
            end else begin
                aligned_current_acc = $signed($unsigned(current_accumulator_s3) >> current_exp_diff);
            end

            // 累加历史值和当前值
            final_accumulator = aligned_history_acc + aligned_current_acc;
        end
    end

    // 更新历史值寄存器
    always_ff @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            history_accumulator  <= '0;
            history_max_exponent <= '0;
            history_valid        <= '0;
            history_any_inf      <= '0;
            history_any_nan      <= '0;
        end else if (end_reduce_s3) begin
            // end_reduce时清除历史值
            history_accumulator  <= '0;
            history_max_exponent <= '0;
            history_valid        <= '0;
            history_any_inf      <= '0;
            history_any_nan      <= '0;
        end else if (psum_en_s3 && en) begin
            // psum_en时更新历史值
            history_accumulator  <= final_accumulator;
            history_max_exponent <= global_max_exp;
            history_valid        <= 1'b1;
            history_any_inf      <= any_inf_s3 | history_any_inf;
            history_any_nan      <= any_nan_s3 | history_any_nan;
        end
    end

    // Stage 4 寄存器
    always_ff @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            accumulator_s4  <= '0;
            max_exponent_s4 <= '0;
            any_inf_s4      <= '0;
            any_nan_s4      <= '0;
            end_reduce_s4   <= '0;
        end else if (en) begin
            accumulator_s4  <= final_accumulator;
            max_exponent_s4 <= global_max_exp;
            any_inf_s4      <= any_inf_s3 | history_any_inf;
            any_nan_s4      <= any_nan_s3 | history_any_nan;
            end_reduce_s4   <= end_reduce_s3;
        end
    end

    //==========================================================================
    // Stage 5: 规格化 + 舍入 + 输出
    //==========================================================================

    // Stage 5 组合逻辑信号
    logic                         result_sign;
    logic [        CSA_WIDTH-1:0] abs_accumulator;
    logic [        LOD_WIDTH-1:0] first_one_pos;
    logic                         no_ones_flag;
    logic [           EWIDTH-1:0] leading_zeros;
    logic [  EWIDTH+GUARD_BITS:0] extended_max_exp;
    logic [EWIDTH+GUARD_BITS-1:0] norm_exponent;
    logic [          CSA_WIDTH:0] norm_significand;
    logic guard, round, sticky;
    logic                         round_up;
    logic [  SIGNIFICAND_WIDTH:0] mantissa_before_round;
    logic [  SIGNIFICAND_WIDTH:0] mantissa_after_round;
    logic [           MWIDTH-1:0] final_mantissa;
    logic [EWIDTH+GUARD_BITS-1:0] adjusted_exponent;
    logic exponent_overflow, exponent_underflow;
    logic              result_is_zero;
    logic [EWIDTH-1:0] final_exponent;
    logic [MWIDTH-1:0] final_mantissa_processed;

    // 符号位和绝对值
    assign result_sign     = accumulator_s4[CSA_WIDTH-1];
    assign abs_accumulator = result_sign ? (~accumulator_s4 + 1) : accumulator_s4;

    // LOD前导零检测
    lod #(
        .LEN(CSA_WIDTH)
    ) u_lod (
        .in_i(abs_accumulator),
        .first_one_o(first_one_pos),
        .no_ones_o(no_ones_flag)
    );

    // 规格化处理
    assign leading_zeros = {2'b0, first_one_pos[LOD_WIDTH-1:0]};
    assign extended_max_exp = max_exponent_s4 + GUARD_BITS + 1;
    assign norm_exponent = (extended_max_exp > leading_zeros) ? extended_max_exp - leading_zeros : '0;

    assign norm_significand = (leading_zeros == 0) ? 
                              abs_accumulator[CSA_WIDTH-1:RWIDTH] :
                              (abs_accumulator << leading_zeros);

    // IEEE 754最近偶数舍入
    assign guard = norm_significand[RWIDTH+1];
    assign round = norm_significand[RWIDTH];
    assign sticky = |norm_significand[RWIDTH-1:0];
    assign round_up = guard & (round | sticky | norm_significand[RWIDTH+2]);

    assign mantissa_before_round = {1'b0, norm_significand[CSA_WIDTH:CSA_WIDTH-SIGNIFICAND_WIDTH]};
    assign mantissa_after_round = mantissa_before_round + round_up;
    assign final_mantissa = mantissa_after_round[MWIDTH-1:0];

    // 调整指数
    assign adjusted_exponent = norm_exponent + mantissa_after_round[SIGNIFICAND_WIDTH];

    // 异常处理
    assign exponent_overflow = (adjusted_exponent >= MAX_EXP);
    assign exponent_underflow = (adjusted_exponent == 0);
    assign result_is_zero = no_ones_flag | (~|abs_accumulator);

    // 处理下溢
    assign final_exponent = exponent_underflow ? EXP_ZEROS : adjusted_exponent[EWIDTH-1:0];
    assign final_mantissa_processed = exponent_underflow ? 
                                     (mantissa_after_round >> (leading_zeros - GUARD_BITS - 1)) :
                                     final_mantissa;

    // 输出寄存器
    always_ff @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            dat_out     <= '0;
            dat_out_vld <= '0;
        end else if (end_reduce_s4 && en) begin
            dat_out_vld <= 1'b1;

            if (any_nan_s4) begin
                dat_out <= NAN;
            end else if (result_is_zero) begin
                dat_out <= '0;
            end else if (exponent_overflow | any_inf_s4) begin
                dat_out <= {result_sign, EXP_ONES, MANT_ZEROS};
            end else begin
                dat_out <= {result_sign, final_exponent, final_mantissa_processed};
            end
        end else begin
            dat_out_vld <= '0;
        end
    end

endmodule
